﻿using System;
using System.Runtime.InteropServices;
using System.Text;
using Security2;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using System.Security.Principal;

namespace Lsa
{
    public class UserRights
    {
        private string computerName;
        private Privileges name;
        private List<IdentityReference2> accounts;

        public string ComputerName
        {
            get { return computerName; }
        }

        public Privileges Name
        {
            get { return name; }
        }

        public ReadOnlyCollection<IdentityReference2> Accounts
        {
            get { return new ReadOnlyCollection<IdentityReference2>(accounts); }
        }

        public UserRights(string computerName, Privileges name, string[] sids)
        {
            this.computerName = computerName;
            this.name = name;

            accounts = new List<IdentityReference2>();
            if (sids != null)
            {
                foreach (var sid in sids)
                {
                    accounts.Add((IdentityReference2)sid);
                }
            }
        }

        #region GetAccountsWithSpecificRight
        public static UserRights GetAccountsWithSpecificRight(string computerName, Privileges privilege)
        {
            return new UserRights(computerName, privilege, LsaLib.EnumerateAccountsWithRight(computerName, privilege));
        }

        public static UserRights GetAccountsWithSpecificRight(Privileges privilege)
        {
            var computerName = Environment.MachineName;
            return GetAccountsWithSpecificRight(computerName, privilege);
        }
        #endregion

        #region GetAllRights
        public static List<UserRights> GetAllRights()
        {
            var computerName = Environment.MachineName;
            return GetAllRights(computerName);
        }

        public static List<UserRights> GetAllRights(string computerName)
        {
            var accountsWithRights = new List<UserRights>();

            foreach (var name in (Privileges[])Enum.GetValues(typeof(Privileges)))
            {
                var sids = LsaLib.EnumerateAccountsWithRight(computerName, name);
                accountsWithRights.Add(new UserRights(computerName, name, sids));
            }

            return accountsWithRights;
        }
        #endregion

        #region GetRightsForAccount
        public static List<UserRights> GetRightsForAccount(IdentityReference2 account)
        {
            var computerName = Environment.MachineName;
            return GetRightsForAccount(computerName, account);
        }

        public static List<UserRights> GetRightsForAccount(string computerName, IdentityReference2 account)
        {
            var userRights = new List<UserRights>();

            var rights = LsaLib.GetAccountRights(computerName, account);

            foreach (var right in rights)
            {
                userRights.Add(new UserRights(computerName, (Privileges)Enum.Parse(typeof(Privileges), right), new string[] { account.Sid }));
            }

            return userRights;
        }
        #endregion

        #region GrantRight
        public static void GrantRight(IdentityReference2 account, Privileges privilege)
        {
            var computerName = Environment.MachineName;

            GrantRight(computerName, account, privilege);
        }

        public static void GrantRight(string computerName, IdentityReference2 account, Privileges privilege)
        {
            LsaLib.AddAccountRights(computerName, account, privilege);
        }
        #endregion 

        #region RevokeRight
        public static void RevokeRight(IdentityReference2 account, Privileges privilege)
        {
            var computerName = Environment.MachineName;

            RevokeRight(computerName, account, privilege);
        }

        public static void RevokeRight(string computerName, IdentityReference2 account, Privileges privilege)
        {
            LsaLib.RemoveAccountRights(computerName, account, privilege);
        }
        #endregion

        public override string ToString()
        {
            return string.Format("{0} ({1})", this.name.ToString(), this.accounts.Count);
        }
    }
}